#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#include <ecgi.h>
#include <memfile.h>

#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xmlsave.h>

#include <xmlsec/buffer.h>
#include <xmlsec/xmldsig.h>
#include <xmlsec/xmltree.h>

#include "common.h"

static void die(int code, char *msg) {
  printf("Status: %d %s\n\n", code, msg);
  exit(0);
}

int main(int argc, char **argv) {
  const char *s, *param = "document", *ip;
  int fd, ret;
  MFILE *m;
  xmlDocPtr doc, prop;
  xmlNodePtr root;
  xmlSecDSigCtxPtr ds;

  close(2);
  ip = getenv("REMOTE_ADDR");
  if(!ip)
    die(500, "No REMOTE_ADDR set");
  fd = open("/tmp/cgi-stderr.log", O_WRONLY|O_CREAT|O_TRUNC, 0666);
  assert(fd >= 0);
  if(fd != 2) {
    close(2);
    if(dup2(fd, 2) != 2)
      die(500, "dup2 failed");
    close(fd);
  }
  assert(cgiInit() == ECGI_SUCCESS);
  cgiSetMaxSize(50000);		/* *handwave* */
  switch((ret = cgiGetKind(param))) {
  case 0:
    printf("Expecting a form variable\n");
    exit(0);
  case CgiKindValue:
    // printf("Expected multipart/form-data transfer");
    s = cgiParam(param);
    goto out;
#if 0
  case CgiKindEmptyFile:
    die(400, "Upload an empty file is just silly");
  case CgiKindFileToBig:
    die(400, "File too big");
#endif    
  default:
    printf("ecgi supplying garbage (%d) in cgiGetKind()", ret);
    exit(0);
  case CgiKindFile:
    break;
  }

  m = cgiGetMFile(param);
  s = mfGetData(m);
out:
#if 1
  fd = open("/tmp/dump", O_CREAT|O_WRONLY|O_TRUNC, 0666);
  write(fd, s, strlen(s));
  close(fd);
#endif
  libSetup();
  doc = xmlParseMemory(s, strlen(s));
  if(!doc)
    die(400, "XML parsing failed");
  root = xmlDocGetRootElement(doc);
  if(!root)
    die(500, "No root element in document");
  if(!xmlStrcmp(xmlSecGetNodeNsHref(root), ns_mikolaj)) {
    if(!xmlStrcmp(xmlSecNodeGetName(root), "compliance")) {
      int result = processCompliance(root, ip);
      fprintf(stderr, "Done with compliance\n");
      if(result)
        printf("Content-type: text/plain\n\nFAIL %d\n", result);
      else
        printf("Content-type: text/plain\n\nOK\n");
      return 0;
    }
    if(!xmlStrcmp(xmlSecNodeGetName(root), "solicitation")) {
      xmlSaveCtxtPtr ctxt;
      ds = processSolicitation(root);
      if(!ds)
	die(500, "Failed to parse document");
      prop = ds->userData;
      printf("Content-type: text/xml\n\n");
      //xmlDocDump(stdout, prop);
      fflush(stdout);
      ctxt = xmlSaveToFd(1, "UTF-8", XML_SAVE_NO_EMPTY|XML_SAVE_NO_DECL);
      xmlSaveDoc(ctxt, prop);
      xmlSaveClose(ctxt);
      return 0;
    }
  }
  die(404, "No handler for document type");
  return 0;
}
